package {{pack}}.autoconf;

import java.io.IOException;
import java.nio.charset.Charset;

import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.NoConnectionReuseStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.protocol.HttpContext;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import org.zalando.logbook.Logbook;
import org.zalando.logbook.httpclient.LogbookHttpRequestInterceptor;
import org.zalando.logbook.httpclient.LogbookHttpResponseInterceptor;
import {{pack}}.logbook.CutOffBodyResponseFilter;

import {{pack}}.utils.Traces;

@Configuration
public class RestAutoConfiguration {

  private static final String TRACE_HEAD = "trace-id";


  @ConditionalOnClass({HttpClient.class})
  @EnableConfigurationProperties(HttpClientProperties.class)
  public static class HttpClientAutoConfiguration {
    private final HttpClientProperties properties;

    public HttpClientAutoConfiguration(HttpClientProperties properties) {
      this.properties = properties;
    }

    @Bean
    @ConditionalOnMissingBean(HttpClient.class)
    public HttpClient httpClient(Logbook logbook) {
      RequestConfig requestConfig = RequestConfig.custom()
              .setConnectTimeout(properties.getConnectTimeOut())
              .setSocketTimeout(properties.getSocketTimeOut()).build();

      HttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig)
          .setUserAgent(properties.getAgent()).setMaxConnPerRoute(properties.getMaxConnPerRoute())
          .addInterceptorFirst(new HttpRequestInterceptor() {
            public void process(final HttpRequest request, final HttpContext context)
                throws HttpException, IOException {
              if (!request.containsHeader(TRACE_HEAD)) {
                request.addHeader(TRACE_HEAD, Traces.getTraceId());
              }
            }
          })
          .addInterceptorLast(new LogbookHttpRequestInterceptor(logbook))
          .addInterceptorLast(new LogbookHttpResponseInterceptor())
          .setMaxConnTotal(properties.getMaxConnTotal()).disableAutomaticRetries()
          .setConnectionReuseStrategy(new NoConnectionReuseStrategy()).build();
      return client;
    }

    
  }



  @ConditionalOnClass({RestTemplate.class,HttpClient.class})
  public static class RestTemplateAutoConfiguration{

    @Bean
    @ConditionalOnMissingBean(RestTemplate.class)
    RestTemplate restTemplate(HttpClient httpClient) {
      RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
      template.getMessageConverters().add(0, new StringHttpMessageConverter(Charset.forName("utf-8")));
      return template;
    }

  }






}
